# -*- coding: utf-8 -*-

import platform
import codecs

from PyQt4.QtCore import *
from PyQt4.QtGui import *

SENTENCE, POLARITY, FEATURE = range(3)

MAGIC_NUMBER = 0x570C4
FILE_VERSION = 1

class Ship(object):

    # inicialização dos atributos da classe Ship
    def __init__(self, TSentence, TPolarity, TFeature):
        self.TSentence = QString(TSentence)   
        self.TPolarity = QString(TPolarity)
        self.TFeature = QString(TFeature)
    
    # explicar o que faz o método __cmp__
    def __cmp__(self, other):
        return QString.localeAwareCompare(self.TSentence.toLower(),
                                          other.TSentence.toLower())
        
class ShipTableModel(QAbstractTableModel):

    # inicialização dos atributos da classe ShipTableModel
    def __init__(self, filename=QString()):
        super(ShipTableModel, self).__init__()
        self.filename = filename
        self.dirty = False
        self.TABELA = []
        self.TPolarities = set()
        self.TFeatures = set()
        
    # explicar o que faz o método sortByCountryOwner, se não estiver utilizando o método comente o código referente ao método
    #relação com o export, sem esse método o export não funciona, 
    def sortByCountryOwner(self):
        def compare(a, b):
            if a.TFeature != b.TFeature:                                           #--- comentar -- 
                return QString.localeAwareCompare(a.TFeature, b.TFeature)
            if a.TPolarity != b.TPolarity:
                return QString.localeAwareCompare(a.TPolarity, b.TPolarity)
            return QString.localeAwareCompare(a.TSentence, b.TSentence)
        self.TABELA = sorted(self.TABELA, compare)
        self.reset()    
    
    # explicar o que faz o método flags, se não estiver utilizando o método comente o código referente ao método
    def flags(self, index):
        if not index.isValid(): #se a posição não for válida deshabilita 
            return Qt.ItemIsEnabled
        return Qt.ItemFlags(QAbstractTableModel.flags(self, index)| #da enable nas coisas da tabela
                            Qt.ItemIsEditable) 
    
    # explicar o que faz o método data, se não estiver utilizando o método comente o código referente ao método
    # colocar cor para determinado nome, se não utilizar o quadrado de TDescription fica na cor preta
    def data(self, index, role=Qt.DisplayRole):
        if not index.isValid() or \
           not (0 <= index.row() < len(self.TABELA)):
            return QVariant()
        ship = self.TABELA[index.row()]
        column = index.column()
        if role == Qt.DisplayRole:
            if column == SENTENCE:
                return QVariant(ship.TSentence)
            elif column == POLARITY:
                return QVariant(ship.TPolarity)
            elif column == FEATURE:
                return QVariant(ship.TFeature)                       

        return QVariant()
   
    # explicar o que faz o método headerData, se não estiver utilizando o método comente o código referente ao método
    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if role == Qt.TextAlignmentRole:
            if orientation == Qt.Horizontal:                                  # É Aqui, onde é colocado o nome de cada coluna do programa
                return QVariant(int(Qt.AlignLeft|Qt.AlignVCenter))
            return QVariant(int(Qt.AlignRight|Qt.AlignVCenter))
        if role != Qt.DisplayRole:
            return QVariant()
        if orientation == Qt.Horizontal:
            if section == SENTENCE:
                return QVariant("Sentence")
            elif section == POLARITY:
                return QVariant("Polarity")
            elif section == FEATURE:
                return QVariant("Feature")

        return QVariant(int(section + 1))

    # conta o número de linhas da tabela  
    def rowCount(self, index=QModelIndex()):
        return len(self.TABELA)

    # conta o número de colunas da tabela
    def columnCount(self, index=QModelIndex()):
        return 3
        
    # explicar o que faz o método setData, se não estiver utilizando o método comente o código referente ao método
    def setData(self, index, value, role=Qt.EditRole):
        if index.isValid() and 0 <= index.row() < len(self.TABELA):
            ship = self.TABELA[index.row()]
            column = index.column()
            if column == SENTENCE:
                ship.TSentence = value.toString()
            elif column == POLARITY:
                ship.TPolarity = value.toString()
            elif column == FEATURE:
                ship.TFeature = value.toString()
            self.dirty = True
#            self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
#                      index, index)
            return True
        return False

    # insere linhas na tabela
    def insertRows(self, position, rows=1, index=QModelIndex()):
        self.beginInsertRows(QModelIndex(), position,
                             position + rows - 1)
        for row in range(rows):
            self.TABELA.insert(position + row, Ship(" ", " ", " ")) #inicialização de cada linha da tabela
        self.endInsertRows()
        self.dirty = True
        return True

    # remove linhas da tabela 
    def removeRows(self, position, rows=1, index=QModelIndex()):
        self.beginRemoveRows(QModelIndex(), position,
                             position + rows - 1)
        self.TABELA = self.TABELA[:position] + \
                     self.TABELA[position + rows:]
        self.endRemoveRows()
        self.dirty = True
        return True

    # explicar o que faz o método load, se não estiver utilizando o método comente o código referente ao método   
    # sem isso, da um erro ligado a ShipTableModel do stestejanelas.py se for retirando coisas, vai dando mais erros.. até chegar em um erro relacionado a própria classe então deixei o método aqui
    def load(self):
        exception = None
        fh = None
        try:
            if self.filename.isEmpty():
                raise IOError, "no filename specified for loading"
            fh = QFile(self.filename)
            if not fh.open(QIODevice.ReadOnly):
                raise IOError, unicode(fh.errorString())
            stream = QDataStream(fh)
            magic = stream.readInt32()
            if magic != MAGIC_NUMBER:
                raise IOError, "unrecognized file type"
            fileVersion = stream.readInt16()
            if fileVersion != FILE_VERSION:
                raise IOError, "unrecognized file type version"
            self.TABELA = []
            while not stream.atEnd():
                TSentence = QString()
                TPolarity = QString()
                TFeature = QString()
                stream >> TSentence >> TPolarity >> TFeature 
                self.TABELA.append(Ship(TSentence, TPolarity, TFeature))
                self.TPolarities.add(unicode(TPolarity))
                self.TFeatures.add(unicode(TFeature))
            self.dirty = False
        except IOError, e:
            exception = e
        finally:
            if fh is not None:
                fh.close()
            if exception is not None:
                raise exception

class ShipDelegate(QItemDelegate):

    # inicialização dos atributos da classe ShipDelegate
    def __init__(self, parent=None):
        super(ShipDelegate, self).__init__(parent)

    # explicar o que faz o método createEditor, se não estiver utilizando o método comente o código referente ao método
    #método que coloca as coisas na tabela, ou seja, coloca o spinbox, os combobox e etc dentro da tabela
    def createEditor(self, parent, option, index):
        if index.column() == POLARITY: 
            combobox = QComboBox(parent)
            combobox.addItems(sorted(index.model().TPolarities))
            combobox.setEditable(True)
            arquivo = codecs.open("./ln2.txt",encoding='utf-8',mode="r")   #abertura da lista de polaridades
            conTWordsdo = arquivo.readlines()
            lista =[]        
            for i in conTWordsdo:
                lista.append(i.replace("\n",""))
            combobox.addItems(sorted(lista))
            return combobox            
        elif index.column() == FEATURE: 
            combobox = QComboBox(parent)
            combobox.addItems(sorted(index.model().TFeatures))
            combobox.setEditable(True)
            arquivo = codecs.open("./ln1.txt",encoding='utf-8',mode="r")  #abertura da lista de features
            conTWordsdo = arquivo.readlines()
            lista = []            
            for i in conTWordsdo:
                lista.append(i.replace("\n",""))
            combobox.addItems(sorted(lista))
            return combobox        
        elif index.column() == SENTENCE:
            editor = QLineEdit(parent)
            self.connect(editor, SIGNAL("returnPressed()"), self.commitAndCloseEditor)
            return editor
        else:
            return QItemDelegate.createEditor(self, parent, option, index)
    
    # explicar o que faz o método commitAndCloseEditor, se não estiver utilizando o método comente o código referente ao método
    #relação com o método anterior, relação com a subsentença e com a descrição
    def commitAndCloseEditor(self):
        editor = self.sender()
        if isinstance(editor, (QTextEdit, QLineEdit)):
            self.emit(SIGNAL("commitData(QWidget*)"), editor)
            self.emit(SIGNAL("closeEditor(QWidget*)"), editor)

    # explicar o que faz o método setModelData, se não estiver utilizando o método comente o código referente ao método
    #Sem esse método, as palavras do grupo de features e os numeros das polaridades sairiam errodos, apareceriam números de ordem crescente para eles ao invés dos mesmos aparecerem, exemplo : casa, ronaldo, show. na hora de escolher show apareceria 3 por ser a posição dele no vetor.
    def setModelData(self, editor, model, index):
        if index.column() in (POLARITY, FEATURE):
            text = editor.currentText()
            if text.length() >= 3:
                model.setData(index, QVariant(text))
        elif index.column() == SENTENCE:
            text = editor.text()
            if text.length() >= 3:
                model.setData(index, QVariant(text))